package com.example.hello.views.badges;

import com.example.hello.*;
import com.example.hello.POJO.*;
import com.example.hello.TextField;
import com.example.hello.views.Collection;
import com.example.hello.views.assignments.Assignments;
import com.example.hello.views.organizations.Organizations;
import com.example.hello.views.tracks.Tracks;
import com.example.hello.views.users.Users;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.*;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.type.TypeReference;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Set;

public class Badge extends Collection {

    public static UserPOJO currentUser;

    private HorizontalLayout layout = new HorizontalLayout();

    private final TextField content = new TextField("Content");
    private final TextField name = new TextField("Name");
    private final ColorPickerArea color = new ColorPickerArea();
    private BootstrapLabel contentLabel = new BootstrapLabel();
    private BootstrapLabel nameLabel = new BootstrapLabel();

    private VerticalLayout edit = new VerticalLayout();
    private VerticalLayout buttons = new VerticalLayout();

    private BadgePOJO badge;

    @Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
        currentUser = ((HelloUI) HelloUI.getCurrent()).getUser();
        if (currentUser == null) currentUser = new UserPOJO();
//        badge = Badge.GETBadge(badge.getEncodedName());
//        if (this.badge == null) this.badge = new BadgePOJO();

        boolean visible = currentUser.isSiteAdmin();
//        edit.setEnabled(visible);
        content.setVisible(visible);
        name.setVisible(visible);
        contentLabel.setVisible(!visible);
        nameLabel.setVisible(!visible);
        color.setEnabled(visible);
        buttons.setVisible(visible);
    }

    public Badge(String NAME, BadgePOJO badge) {
        super(NAME);
        this.badge = badge;

        currentUser = ((HelloUI) HelloUI.getCurrent()).getUser();
        if (currentUser == null) currentUser = new UserPOJO();
        if (this.badge == null) this.badge = new BadgePOJO();

        initBadge();
    }

    public void initBadge() {
        BootstrapButton submit = new BootstrapButton("Submit Changes");
        BootstrapButton delete = new BootstrapButton("Delete Badge");

        content.setValue(badge.getContent());
        name.setValue(badge.getName());
        contentLabel.setText(badge.getContent());
        contentLabel.setCaption("Content");
        nameLabel.setText(badge.getName());
        nameLabel.setCaption("Name");
        int[] rgb = badge.toHexColor();
        color.setColor(new Color(rgb[0], rgb[1], rgb[2]));
        submit.addListener(new Listener() {
            @Override
            public void componentEvent(Event event) {
                String _id = badge.get_id();
                badge.set_id(null);
                badge.setContent(content.getValue());
                badge.setName(name.getEncodedValue());
                badge.setColor(color.getColor().getCSS().substring(1));

                ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
                String json = "";
                try {
                    json = ow.writeValueAsString(badge);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                badge.set_id(_id);
                if (HttpRequest.executePut(NAME, json)) {
                    HelloUI.getCurrent().getNavigator().removeView(NAME);
                    Badge newView = new Badge(badge.getEncodedName(), badge);
                    HelloUI.getCurrent().getNavigator().addView(newView.NAME, newView);
                    HelloUI.getCurrent().getNavigator().navigateTo(NAME);
                } else {
                    getUI().getNavigator().navigateTo(NAME);
                }
            }
        });
        delete.addListener(new Listener() {
            @Override
            public void componentEvent(Event event) {
                Badges.removeBadge(badge);
                HelloUI.getCurrent().getNavigator().navigateTo(Badges.NAME);
            }
        });

        color.setCaption("Color");
        color.setTextfieldVisibility(true);

        Label colorLabel = new Label(color.getColor().getCSS());
        colorLabel.setCaption("");
        HorizontalLayout colorLayout = new HorizontalLayout(color, new HSpacer(20), colorLabel);
        colorLayout.setComponentAlignment(colorLabel, Alignment.MIDDLE_CENTER);

        edit.addComponent(content);
        edit.addComponent(contentLabel);
        edit.addComponent(new VSpacer(10));
        edit.addComponent(name);
        edit.addComponent(nameLabel);
        edit.addComponent(new VSpacer(10));
        edit.addComponent(colorLayout);

        buttons.addComponent(submit);
        buttons.addComponent(new VSpacer(20));
        buttons.addComponent(delete);

        com.example.hello.Badge badge = this.badge.createBadge();
        layout.addComponent(new HSpacer(79));
        layout.addComponent(badge);
        layout.addComponent(new HSpacer(79));
        layout.addComponent(edit);
        layout.addComponent(new HSpacer(20));
        layout.addComponent(buttons);
        layout.setComponentAlignment(buttons, Alignment.MIDDLE_CENTER);
        layout.setComponentAlignment(badge, Alignment.MIDDLE_CENTER);

        BootstrapButton back = new BootstrapButton("Back");
        back.addListener(new Listener() {
            @Override
            public void componentEvent(Event test) {
                getUI().getNavigator().navigateTo(Badges.NAME);
            }
        });

        addComponent(layout);
        addComponent(new VSpacer(20));
        addComponent(back);
    }

    /**
     * These static methods are intended to be used as an alternative to the HttpRequest class
     * directly. The GET(String get) method can technically return any value type, however this
     * is useful if the user of this methods knows the type of the value that should be returned.
     *
     * These methods currently reside in this View due to this View's name relationship with
     * these methods function. It might be a good idea to move these methods elsewhere later
     * (perhaps in a helper class whose sole purpose is to return the proper POJO).
     */
    public static BadgePOJO GET(String get) {
        BadgePOJO badge = new BadgePOJO();
        try {
            String json = HttpRequest.GET(get);
            ObjectMapper mapper = new ObjectMapper();
            badge = mapper.readValue(json, new TypeReference<BadgePOJO>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return badge;
    }

    public static BadgePOJO GETBadge(String badgeName) {
        BadgePOJO badge = new BadgePOJO();
        try {
            String json = HttpRequest.GET(Badges.NAME + "/" + badgeName);
            ObjectMapper mapper = new ObjectMapper();
            badge = mapper.readValue(json, new TypeReference<BadgePOJO>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return badge;
    }

    /**
     * This method is intended to be called after changes have been made to the resource
     * associated with this View. Since the View is persistent due to its initialization
     * (unlike Users, Organizations, etc.), a new View must be created to reflect any changes.
     */
    private static void refreshView(BadgePOJO badge) {
        HelloUI.getCurrent().getNavigator().removeView(Badges.NAME + "/" + badge.getEncodedName());
        Badge newView = new Badge(badge.getEncodedName(), badge);
        HelloUI.getCurrent().getNavigator().addView(newView.NAME, newView);
        HelloUI.getCurrent().getNavigator().navigateTo(newView.NAME);
    }

    public static boolean changeName(BadgePOJO badge, String oldName, String newName) {
        Set<TrackPOJO> tracks = Tracks.GETTracks("?badge=" + badge.getEncodedName());
        List<AssignmentPOJO> assignments = Assignments.GETAssignments("?badge=" + badge.getEncodedName());
        Set<UserPOJO> users = Users.GETUsers("?badge=" + badge.getEncodedName());

        badge.setName(newName);
        for (TrackPOJO org : tracks) {
            org.removeBadge(oldName);
            org.addBadge(newName);
            org.update();
        }
        for (AssignmentPOJO assignment : assignments) {
            assignment.removeBadge(oldName);
            assignment.addBadge(newName);
            assignment.update();
        }
        for (UserPOJO user : users) {
            user.removeBadge(oldName);
            user.addBadge(newName);
            user.update();
        }

        return POJO.update(Badges.NAME + "/" + oldName, badge);
    }

}